/*
* Copyright (C) 2006, 2007 Dennis Hunziker, Ueli Kistler
* Copyright (C) 2007 Reto Schuettel, Robin Stocker
*
* IFS Institute for Software, HSR Rapperswil, Switzerland
*
*/
package org.python.pydev.refactoring.core.base;
import java.io.File;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.python.pydev.core.IGrammarVersionProvider;
import org.python.pydev.core.IIndentPrefs;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.MisconfigurationException;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.editor.autoedit.DefaultIndentPrefs;
import org.python.pydev.editor.autoedit.TestIndentPrefs;
import org.python.pydev.parser.jython.ParseException;
import org.python.pydev.parser.jython.TokenMgrError;
import org.python.pydev.parser.jython.ast.factory.AdapterPrefs;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.refactoring.ast.PythonModuleManager;
import org.python.pydev.refactoring.ast.adapters.AbstractScopeNode;
import org.python.pydev.refactoring.ast.adapters.IClassDefAdapter;
import org.python.pydev.refactoring.ast.adapters.ModuleAdapter;
import org.python.pydev.refactoring.ast.visitors.VisitorFactory;
import com.aptana.shared_core.structure.Tuple;
public class RefactoringInfo {
private IFile sourceFile;
private IDocument doc;
private ITextSelection userSelection;
private ITextSelection extendedSelection;
private ModuleAdapter moduleAdapter;
private final IPythonNature nature;
private final IGrammarVersionProvider versionProvider;
public final IIndentPrefs indentPrefs;
private PythonModuleManager moduleManager;
private AbstractScopeNode<?> scopeAdapter;
private IProject project;
private File realFile;
public RefactoringInfo(PyEdit edit) throws MisconfigurationException {
this(edit, (ITextSelection) edit.getSelectionProvider().getSelection());
};
/**
* Constructor to be used only in tests!
*/
public RefactoringInfo(IDocument document, ITextSelection selection, IGrammarVersionProvider versionProvider) {
this.sourceFile = null;
this.nature = null;
this.versionProvider = versionProvider;
this.doc = document;
this.indentPrefs = PydevPlugin.getDefault() == null ? new TestIndentPrefs(document.get().indexOf('\t') < 0, 4)
: DefaultIndentPrefs.get();
initInfo(selection);
}
public RefactoringInfo(PyEdit edit, ITextSelection selection) throws MisconfigurationException {
IEditorInput input = edit.getEditorInput();
this.indentPrefs = edit.getIndentPrefs();
IPythonNature localNature = edit.getPythonNature();
if (input instanceof IFileEditorInput) {
IFileEditorInput editorInput = (IFileEditorInput) input;
this.sourceFile = editorInput.getFile();
this.realFile = sourceFile != null ? sourceFile.getLocation().toFile() : null;
} else {
this.realFile = edit.getEditorFile();
}
if (localNature == null) {
Tuple<IPythonNature, String> infoForFile = PydevPlugin.getInfoForFile(this.realFile);
if (infoForFile != null && infoForFile.o1 != null) {
localNature = infoForFile.o1;
}
}
this.nature = localNature;
this.doc = edit.getDocument();
this.project = edit.getProject();
versionProvider = this.nature;
initInfo(selection);
}
private void initInfo(ITextSelection selection) {
if (this.nature != null) {
this.moduleManager = new PythonModuleManager(nature);
}
try {
this.moduleAdapter = VisitorFactory.createModuleAdapter(moduleManager, realFile, doc, nature,
this.versionProvider);
} catch (Throwable e) {
throw new RuntimeException(e);
}
this.extendedSelection = null;
this.userSelection = moduleAdapter.normalizeSelection(selection);
}
public IProject getProject() {
return project;
}
public ModuleAdapter getModuleAdapter() {
return moduleAdapter;
}
public List<IClassDefAdapter> getClasses() {
return moduleAdapter.getClasses();
}
public IFile getSourceFile() {
return this.sourceFile;
}
public IDocument getDocument() {
return this.doc;
}
public ITextSelection getExtendedSelection() {
if (this.extendedSelection == null) {
this.extendedSelection = new TextSelection(this.doc, this.userSelection.getOffset(),
this.userSelection.getLength());
if (getScopeAdapter() != null) {
this.extendedSelection = moduleAdapter.normalizeSelection(VisitorFactory.createSelectionExtension(
getScopeAdapter(), this.extendedSelection));
}
}
return extendedSelection;
}
public ITextSelection getUserSelection() {
return userSelection;
}
public ModuleAdapter getParsedExtendedSelection() {
String source = normalizeSourceSelection(getExtendedSelection());
if (source.length() > 0) {
try {
return VisitorFactory.createModuleAdapter(moduleManager, null, new Document(source), nature,
this.versionProvider);
} catch (TokenMgrError e) {
return null;
} catch (ParseException e) {
/* Parse Exception means the current selection is invalid, discard and return null */
return null;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
return null;
}
public ModuleAdapter getParsedUserSelection() {
ModuleAdapter parsedAdapter = null;
String source = normalizeSourceSelection(this.userSelection);
if (this.userSelection != null && source.length() > 0) {
try {
parsedAdapter = VisitorFactory.createModuleAdapter(moduleManager, null, new Document(source), nature,
this.versionProvider);
} catch (TokenMgrError e) {
return null;
} catch (ParseException e) {
/* Parse Exception means the current selection is invalid, discard and return null */
return null;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
return parsedAdapter;
}
public String normalizeSourceSelection(ITextSelection selection) {
String selectedText = "";
if (selection.getText() != null) {
selectedText = selection.getText().trim();
}
if (selectedText.length() == 0) {
return "";
}
try {
return normalizeBlockIndentation(selection, selectedText);
} catch (Throwable e) {
/* TODO: uncommented empty exception catch all */
}
return selectedText;
}
private String normalizeBlockIndentation(ITextSelection selection, String selectedText) throws Throwable {
String[] lines = selectedText.split("\\n");
if (lines.length < 2) {
return selectedText;
}
String firstLine = doc.get(doc.getLineOffset(selection.getStartLine()),
doc.getLineLength(selection.getStartLine()));
String lineDelimiter = TextUtilities.getDefaultLineDelimiter(doc);
String indentation = "";
int bodyIndent = 0;
while (firstLine.startsWith(" ")) {
indentation += " ";
firstLine = firstLine.substring(1);
bodyIndent += 1;
}
if (bodyIndent > 0) {
StringBuffer selectedCode = new StringBuffer();
for (String line : lines) {
if (line.startsWith(indentation)) {
selectedCode.append(line.substring(bodyIndent) + lineDelimiter);
} else {
selectedCode.append(line + lineDelimiter);
}
}
selectedText = selectedCode.toString();
}
return selectedText;
}
public IClassDefAdapter getScopeClass() {
return moduleAdapter.getScopeClass(getUserSelection());
}
public IPythonNature getNature() {
return nature;
}
public List<IClassDefAdapter> getScopeClassAndBases() throws MisconfigurationException {
return moduleAdapter.getClassHierarchy(getScopeClass());
}
public AbstractScopeNode<?> getScopeAdapter() {
if (scopeAdapter == null) {
scopeAdapter = moduleAdapter.getScopeAdapter(userSelection);
}
return scopeAdapter;
}
public boolean isSelectionExtensionRequired() {
return !(this.getUserSelection().getOffset() == this.getExtendedSelection().getOffset() && this
.getUserSelection().getLength() == this.getExtendedSelection().getLength());
}
public String getNewLineDelim() {
return TextUtilities.getDefaultLineDelimiter(this.doc);
}
public AdapterPrefs getAdapterPrefs() {
return new AdapterPrefs(getNewLineDelim(), versionProvider);
}
public PySelection getPySelection() {
return new PySelection(doc, userSelection);
}
/**
* @return
*/
public IGrammarVersionProvider getVersionProvider() {
return this.versionProvider;
}
// public Workspace getWorkspace() {
// /* create or get the workspace */
//
// if(workspace == null){
// workspace = createWorkspace();
// }
//
// return workspace;
// }
//
// private Workspace createWorkspace() {
// LinkedList<String> srcPath = new LinkedList<String>();
//
// Set<String> paths;
// try{
// paths = nature.getPythonPathNature().getProjectSourcePathSet(true);
// }catch(CoreException e){
// throw new RuntimeException(e);
// }
// for(String path:paths){
// IFolder folder = project.getParent().getFolder(new Path(path));
// /* get the source folder's path relative to the project */
// String relativePath = folder.getProjectRelativePath().toString();
// srcPath.add(relativePath);
// }
//
// return new Workspace(project.getLocation().makeAbsolute().toFile(), srcPath, sysPath);
// }
//
// public Module getModule() {
// File file = this.realFile;
// Workspace workspace = this.getWorkspace();
//
// Module module = workspace.getModule(file);
// return module;
// }
//
// /**
// * Returns the NameUse of the currently selected variable
// *
// * @return the currently selected nameUse
// */
// public Use findSelectedUse() {
// List<Use> uses = getModule().getContainedUses();
//
// int selectionOffset = userSelection.getOffset();
//
// for(Use use:uses){
// NameAdapter name = use.getName();
// int nodeLength = name.getId().length();
// int nodeOffsetBegin = NodeUtils.getOffset(this.doc, name.getNode());
//
// int nodeOffsetEnd = nodeOffsetBegin + nodeLength;
//
// if(selectionOffset >= nodeOffsetBegin && selectionOffset <= nodeOffsetEnd){
// return use;
// }
// }
//
// return null;
// }
// public PythonTypeInferencer getTypeInferencer() {
// if(inferencer == null){
// inferencer = new PythonTypeInferencer();
// }
// return inferencer;
// }
//
// public IFile getFileForModule(IModule module) {
// if(project != null){
// String relativePath = module.getRelativePath();
// IPath path = new Path(relativePath);
// IFile file = project.getFile(path);
// return file;
// }else{
// return null;
// }
// }
}